﻿#include "server.h"
#include <qdebug>

AbstractHandler::AbstractHandler(DataExchange::DataQuery::AsyncService* service, ServerCompletionQueue* cq)
	: service_(service), cq_(cq), status_(HandlerStatus::CREATE) {

}

void DataServer::initContractsResponse()
{

	using T = MethodCallData<DataExchange::ListRequest, DataExchange::ContractsResponse>;
	auto cd = new T();

	cd->process_cb = [this](void* cd) {
		initContractsResponse();
		App::instance()->dataReader()->listContracts(0, &((T*)cd)->reply);
		((T*)cd)->responder.Finish(((T*)cd)->reply, Status::OK, cd);
		((T*)cd)->status = T::HandlerStatus::FINISH;
	};
	cd->finish_cb = [this](void* t) { delete (T*)t;  };

	m_service.RequestListContracts(&((T*)cd)->ctx, &((T*)cd)->request, &((T*)cd)->responder, m_cq.get(), m_cq.get(), cd);
	((T*)cd)->status = T::HandlerStatus::PROCESS;
}
void DataServer::initFactorsResponse()
{
	using T = MethodCallData<DataExchange::ListRequest, DataExchange::FactorsResponse>;
	auto cd = new T();

	cd->process_cb = [this](void* cd) {
		initFactorsResponse();
		App::instance()->dataReader()->listFactors(0, &((T*)cd)->reply);
		((T*)cd)->responder.Finish(((T*)cd)->reply, Status::OK, cd);
		((T*)cd)->status = T::HandlerStatus::FINISH;
	};
	cd->finish_cb = [this](void* t) { delete (T*)t;  };

	m_service.RequestListFactors(&((T*)cd)->ctx, &((T*)cd)->request, &((T*)cd)->responder, m_cq.get(), m_cq.get(), cd);
	((T*)cd)->status = T::HandlerStatus::PROCESS;
}
void DataServer::initStrategiesResponse()
{
	using T = MethodCallData<DataExchange::ListRequest, DataExchange::StrategiesResponse>;
	auto cd = new T();

	cd->process_cb = [this](void* cd) {
		initStrategiesResponse();
		App::instance()->dataReader()->listStrategies(0, &((T*)cd)->reply);
		((T*)cd)->responder.Finish(((T*)cd)->reply, Status::OK, cd);
		((T*)cd)->status = T::HandlerStatus::FINISH;
	};
	cd->finish_cb = [this](void* t) { delete (T*)t;  };

	m_service.RequestListStrategies(&((T*)cd)->ctx, &((T*)cd)->request, &((T*)cd)->responder, m_cq.get(), m_cq.get(), cd);
	((T*)cd)->status = T::HandlerStatus::PROCESS;
}
void DataServer::initCollectionsResponse()
{
	using T = MethodCallData<DataExchange::ListRequest, DataExchange::CollectionsResponse>;
	auto cd = new T();

	cd->process_cb = [this](void* cd) {
		initCollectionsResponse();
		App::instance()->dataReader()->listCollections(0, &((T*)cd)->reply);
		((T*)cd)->responder.Finish(((T*)cd)->reply, Status::OK, cd);
		((T*)cd)->status = T::HandlerStatus::FINISH;
	};
	cd->finish_cb = [this](void* t) { delete (T*)t;  };

	m_service.RequestListCollections(&((T*)cd)->ctx, &((T*)cd)->request, &((T*)cd)->responder, m_cq.get(), m_cq.get(), cd);
	((T*)cd)->status = T::HandlerStatus::PROCESS;
}
void DataServer::initCollectionDetail()
{
	using T = MethodCallData<DataExchange::ItemRequest, DataExchange::Collection>;
	auto cd = new T();

	cd->process_cb = [this](void* cd) {
		initCollectionDetail();
		App::instance()->dataReader()->collectionDetail(0, ((T*)cd)->request.rowid(),&((T*)cd)->reply);
		((T*)cd)->responder.Finish(((T*)cd)->reply, Status::OK, cd);
		((T*)cd)->status = T::HandlerStatus::FINISH;
	};
	cd->finish_cb = [this](void* t) { delete (T*)t;  };

	m_service.RequestCollectionDetail(&((T*)cd)->ctx, &((T*)cd)->request, &((T*)cd)->responder, m_cq.get(), m_cq.get(), cd);
	((T*)cd)->status = T::HandlerStatus::PROCESS;
}
DataServer:: ~DataServer() {
	m_server->Shutdown();
	m_cq->Shutdown();
}
void DataServer::run() {
	std::string server_address("0.0.0.0:5000");
	ServerBuilder builder;
	builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
	builder.RegisterService(&m_service);
	m_cq = builder.AddCompletionQueue();
	m_server = builder.BuildAndStart();
	std::cout << "Server listening on " << server_address << std::endl;
	handleRpc();
}
void DataServer::handleRpc() {

	//用于读取call data中的status，所以实例化成任意类型均可
	using T = MethodCallData<DataExchange::ListRequest, DataExchange::ContractsResponse>;

	initContractsResponse();
	initCollectionsResponse();
	initFactorsResponse();
	initStrategiesResponse();
	initCollectionDetail();
	void* tag;
	bool ok;
	while (true) {
		GPR_ASSERT(m_cq->Next(&tag, &ok));
		qDebug() << "event happed.";
		GPR_ASSERT(ok);
		switch(((T*)tag)->status)
		{
		case T::HandlerStatus::PROCESS:
			((T*)tag)->process_cb(tag);
			break;
		case T::HandlerStatus::FINISH:
			((T*)tag)->finish_cb(tag);
			break;
		default:
			break;
		}

			

	}
}






ListContracts::ListContracts(DataExchange::DataQuery::AsyncService* service, ServerCompletionQueue* cq):responder_(&ctx_),AbstractHandler(service, cq)
{
	run();
}

void ListContracts::run()
{
	switch (status_)
	{
	case HandlerStatus::CREATE:
		status_ = HandlerStatus::PROCESS;
		service_->RequestListContracts(&ctx_, &request_, &responder_, cq_, cq_, this);
		break;
	case HandlerStatus::PROCESS:
	{		
		new ListContracts(service_, cq_);
		App::instance()->dataReader()->listContracts(0,&reply_);
		status_ = HandlerStatus::FINISH;
		responder_.Finish(reply_, Status::OK, this);
		break;
	}
	case HandlerStatus::FINISH:
	default:
		GPR_ASSERT(HandlerStatus::FINISH == status_);
		delete this;
		break;
	}
}

ListCollections::ListCollections(DataExchange::DataQuery::AsyncService* service, ServerCompletionQueue* cq):responder_(&ctx_), AbstractHandler(service, cq)
{
	run();
}

void ListCollections::run()
{
	switch (status_)
	{
	case HandlerStatus::CREATE:
		status_ = HandlerStatus::PROCESS;
		service_->RequestListCollections(&ctx_, &request_, &responder_, cq_, cq_, this);
		break;
	case HandlerStatus::PROCESS:
	{
		new ListCollections(service_, cq_);
		App::instance()->dataReader()->listCollections(0, &reply_);
		status_ = HandlerStatus::FINISH;
		responder_.Finish(reply_, Status::OK, this);
		break;
	}
	case HandlerStatus::FINISH:
	default:
		GPR_ASSERT(HandlerStatus::FINISH == status_);
		delete this;
		break;
	}
}

